package com.bckj.fastboot.core.web.repeat.strategy;

import com.bckj.fastboot.core.jackson.JsonUtils;
import com.bckj.fastboot.core.redis.RedisOps;
import com.bckj.fastboot.core.util.WebUtils;
import com.bckj.fastboot.core.web.repeat.RepeatSubmit;
import com.bckj.fastboot.core.web.repeat.RepeatSubmitTypes;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.concurrent.TimeUnit;

@RequiredArgsConstructor
public class SameUrlDataRepeatSubmitStrategy implements RepeatSubmitStrategy {

    private static final String KEY_PREFIX = "resubmit:sud:";

    private final RedisOps redisOps;

    @Override
    public String getType() {
        return RepeatSubmitTypes.SAME_URL_DATA;
    }

    @Override
    public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) {
        // 1. 获取请求 URL
        String url = request.getRequestURI();

        // 2. 计算请求体哈希（仅处理非空请求体）
        String bodyHash = getRequestBodyHash(request);

        // 3. 生成 Redis 唯一键（格式：duplicate:req:{method}:{url}:{bodyHash}）
        String redisKey = getKey(url, bodyHash);

        // 4. 原子性校验并设置 Redis 键（SETNX：仅当键不存在时设置）
        boolean setIfAbsent = Boolean.TRUE.equals(redisOps
                .setIfAbsent(redisKey, "1", annotation.interval(), TimeUnit.MILLISECONDS));

        // 5. 返回结果
        return !setIfAbsent;
    }

    private String getRequestBodyHash(HttpServletRequest request) {
        String body = WebUtils.getBodyStr(request);
        if (StringUtils.isBlank(body)) {
            body = JsonUtils.toJsonStr(request.getParameterMap());
        }
        // 计算 MD5 哈希（可替换为 SHA-256 提高安全性）
        return DigestUtils.md5Hex(body);
    }

    private String getKey(String url, String bodyHash) {
        return KEY_PREFIX + url.replace("/", "") + ":" + bodyHash;
    }
}
